#include "stdafx.h"
#include "rc4.h"
#include "stdafx.h"
#include <wincrypt.h>
#include "malloc.h"

#define BUFFER_SIZE 256

static void swap_byte(unsigned char *a, unsigned char *b);

// Licens typer
const char EBAS_STANDARD[255]	= "STANDARD";
const char EBAS_FAKTURA[255]	= "INVOICE";
const char EBAS_EKSAMEN[255]	= "EXAM";
const char EBAS_INTERNET[255]	= "INTERNET";
const char EBAS_TRIAL[255]		= "TRIAL";

void prepare_key(unsigned char *key_data_ptr, int key_data_len, rc4_key *key)
{
    unsigned char swapByte;
    unsigned char index1;
    unsigned char index2;
    unsigned char* state;
    short counter;     
    
    state = &key->state[0];         
    for(counter = 0; counter < 256; counter++)              
    state[counter] = counter;               
    key->x = 0;     
    key->y = 0;     
    index1 = 0;     
    index2 = 0;             
    for(counter = 0; counter < 256; counter++)      
    {               
         index2 = (key_data_ptr[index1] + state[counter] +
            index2) % 256;                
         swap_byte(&state[counter], &state[index2]);            

         index1 = (index1 + 1) % key_data_len;  
    }       
}

void rc4(unsigned char *buffer_ptr, int buffer_len, rc4_key *key)
{ 
    unsigned char x;
    unsigned char y;
    unsigned char* state;
    unsigned char xorIndex;
    short counter;              
    
    x = key->x;     
    y = key->y;     
    
    state = &key->state[0];         
    for(counter = 0; counter < buffer_len; counter ++)      
    {               
         x = (x + 1) % 256;                      
         y = (state[x] + y) % 256;               
         swap_byte(&state[x], &state[y]);                        
              
         xorIndex = (state[x] + state[y]) % 256;                 
              
         buffer_ptr[counter] ^= state[xorIndex];         
     }               
     key->x = x;     
     key->y = y;
}

static void swap_byte(unsigned char *a, unsigned char *b)
{
    unsigned char swapByte; 
    
    swapByte = *a; 
    *a = *b;      
    *b = swapByte;
}

void write_file(const char * filename, unsigned char * data, long length)
{
	FILE * fp = fopen(filename, "w+");
	if (fp) {
		fwrite(data, 1, length, fp);
		fclose(fp);
	}
}

void make_hash(const char * data, BYTE ** hash, long * len)
{
	HCRYPTPROV hProv = 0;
	HCRYPTHASH hHash = 0;
	BYTE *pbHash = NULL;
	DWORD dwHashLen;

	BYTE * pbBuffer = NULL;
	DWORD dwCount;
	DWORD i;
	unsigned long bufLen = 0;

	if(!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, 0)) {
		return;
	}
	if(!CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash)) {
		return;
	}

	bufLen = strlen(data);

	pbBuffer = (BYTE*)malloc(bufLen +1);
	memset(pbBuffer, 0, bufLen +1);

	// Fill the buffer with data.
	for(i = 0 ; i < bufLen ; i++) {
		pbBuffer[i] = (BYTE)data[i];
	}

	if(!CryptHashData(hHash, pbBuffer, bufLen, 0)) {
		return;
	}

	dwCount = sizeof(DWORD);
	if(!CryptGetHashParam(hHash, HP_HASHSIZE, (BYTE *)&dwHashLen, &dwCount, 0)) {
		return;
	}
	if((pbHash = (unsigned char*)malloc(dwHashLen)) == NULL) {
		return;
	}

	if(!CryptGetHashParam(hHash, HP_HASHVAL, pbHash, &dwHashLen, 0)) {
		return;
	}

	*hash = pbHash;
	*len = dwHashLen;

	if(hHash) CryptDestroyHash(hHash);
	if(hProv) CryptReleaseContext(hProv,0);
}

void gen_number(BYTE ** random, long * length)
{
	HCRYPTPROV hProv = 0;
	BYTE *pbHash = NULL;
	BYTE * pbBuffer = NULL;
	unsigned int aChar = 0;

	const unsigned long bufLen = 16;

	if (*random)
		return;

	if(!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, 0)) {
		return;
	}

	pbBuffer = (BYTE*)malloc(bufLen +1);
	memset(pbBuffer, 0, bufLen +1);

	CryptGenRandom(hProv, bufLen, pbBuffer);

	(*random) = (BYTE*)malloc(bufLen +1+3);
	memset((*random), 0, bufLen +1+3);

	char holder[256];
	strcpy(holder, "0");

	int i = 0;
	for (i=0; i<bufLen; i++) {
		aChar = (unsigned int)pbBuffer[i];

		char temp[4];
		itoa(aChar % 10, temp, 10);		
		strcat(holder, temp);
	}

	char formated[256];
	strcpy(formated, "0");

	for (i=0; i<16; i++) {
		char *pTemp = &holder[i];
		strncat(formated, (char*)pTemp, 1);
		if ((i+1)%4 == 0 && (i+1) != 16)
			strcat(formated, "-");
	}

	strcpy(holder, formated);

	char *pHolder = &holder[1];
	strncpy((char*)(*random), pHolder, bufLen +3);

	*length = bufLen;

	if (pbBuffer)
		free(pbBuffer);

	if(hProv) CryptReleaseContext(hProv,0);
}

void make_licens_key(const char * data, BYTE ** key, long * len)
{
	HCRYPTPROV hProv = 0;
	HCRYPTHASH hHash = 0;
	BYTE *pbHash = NULL;
	DWORD dwHashLen;

	int step = 0;
	BYTE * pbBuffer = NULL;
	DWORD dwCount;
	DWORD i;
	long bufLen = strlen(data);
	
	char tempData[255];
	strncpy(tempData, data, 255);

	if(!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, 0)) {
		return;
	}
	if(!CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash)) {
		return;
	}

	pbBuffer = (BYTE*)malloc(bufLen +1);
	memset(pbBuffer, 0, bufLen +1);

	// Fill the buffer with data.
	for(step = 0 ; step < bufLen ; step++) {
		pbBuffer[step] = (BYTE)tempData[step];
	}

	if(!CryptHashData(hHash, pbBuffer, bufLen, 0)) {
		return;
	}

	dwCount = sizeof(DWORD);
	if(!CryptGetHashParam(hHash, HP_HASHSIZE, (BYTE *)&dwHashLen, &dwCount, 0)) {
		return;
	}
	if((pbHash = (unsigned char*)malloc(dwHashLen)) == NULL) {
		return;
	}

	if(!CryptGetHashParam(hHash, HP_HASHVAL, pbHash, &dwHashLen, 0)) {
		return;
	}

	char holder[256];
	strcpy(holder, "0");

	for (step=0; step<bufLen; step++) {
		unsigned int aChar = (unsigned int)pbHash[step];

		char temp[4];
		itoa(aChar % 10, temp, 10);		
		strcat(holder, temp);
	}

	char formated[256];
	strcpy(formated, "0");

	for (i=0; i<16; i++) {
		char *pTemp = &holder[i];
		strncat(formated, (char*)pTemp, 1);
		if ((i+1)%4 == 0 && (i+1) != 16)
			strcat(formated, "-");
	}

	strcpy(holder, formated);

	*key = (BYTE*)malloc(bufLen +3+1);
	memset((*key), 0, bufLen +3+1);

	char *pHolder = &holder[1];
	strncpy((char*)(*key), pHolder, bufLen +3);

	*len = strlen((char*)(*key));

	if(hHash) CryptDestroyHash(hHash);
	if(hProv) CryptReleaseContext(hProv,0);
}

void make_fixed_salt(long length, BYTE ** random)
{
	HCRYPTPROV hProv = 0;
	BYTE *pbHash = NULL;
	BYTE * pbBuffer = NULL;

	if (*random)
		return;

	if(!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, 0)) {
		return;
	}

	pbBuffer = (BYTE*)malloc(length +1);
	memset(pbBuffer, 0, length +1);

	CryptGenRandom(hProv, length, pbBuffer);

	*random = pbBuffer;

	if(hProv) CryptReleaseContext(hProv,0);
}